home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / SLIP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-19  |  5.1 KB  |  244 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "asy.h"
  11. #include "trace.h"
  12.  
  13. extern struct mbuf *Hopper;
  14. int kiss_ioctl(),slip_send();
  15. int16 asy_recv();
  16. static int slipq();
  17. static void asy_start();
  18. static struct mbuf *slip_encode();
  19.  
  20. /* Slip level control structure */
  21. struct slip Slip[ASY_MAX];
  22.  
  23. /* Send routine for point-to-point slip
  24.  * This is a trivial function since there is no slip link-level header
  25.  */
  26. int
  27. slip_send(data,iface,gateway,prec,del,tput,rel)
  28. struct mbuf *data;    /* Buffer to send */
  29. struct iface *iface;    /* Pointer to interface control block */
  30. int32 gateway;        /* Ignored (SLIP is point-to-point) */
  31. int prec;
  32. int del;
  33. int tput;
  34. int rel;
  35. {
  36.     if(iface == NULLIF){
  37.         free_p(data);
  38.         return -1;
  39.     }
  40.     return (*iface->raw)(iface,data);
  41. }
  42. /* Send a raw slip frame -- also trivial */
  43. int
  44. slip_raw(iface,data)
  45. struct iface *iface;
  46. struct mbuf *data;
  47. {
  48.     dump(iface,IF_TRACE_OUT,Slip[iface->dev].type,data);
  49.     /* Queue a frame on the slip output queue and start transmitter */
  50.     return slipq(iface->dev,data);
  51. }
  52. /* Encode a raw packet in slip framing, put on link output queue, and kick
  53.  * transmitter
  54.  */
  55. static int
  56. slipq(dev,data)
  57. int16 dev;        /* Serial line number */
  58. struct mbuf *data;    /* Buffer to be sent */
  59. {
  60.     register struct slip *sp;
  61.     struct mbuf *bp;
  62.  
  63.     if((bp = slip_encode(data)) == NULLBUF)
  64.         return -1;    
  65.  
  66.     sp = &Slip[dev];
  67.     enqueue(&sp->sndq,bp);
  68.     sp->sndcnt++;
  69.     asy_start(dev);
  70.     return 0;
  71. }
  72. /* Start output, if possible, on asynch device dev */
  73. static void
  74. asy_start(dev)
  75. int16 dev;
  76. {
  77.     register struct slip *sp;
  78.     char i_state;
  79.  
  80.     i_state = dirps();
  81.     if(!stxrdy(dev)){
  82.         restore(i_state);
  83.         return;        /* Transmitter not ready */
  84.     }
  85.     sp = &Slip[dev];
  86.     if(sp->tbp != NULLBUF){
  87.         /* transmission just completed */
  88.         free_p(sp->tbp);
  89.         sp->tbp = NULLBUF;
  90.     }
  91.     if(sp->sndq == NULLBUF){
  92.         restore(i_state);
  93.         return;    /* No work */
  94.     }
  95.     sp->tbp = dequeue(&sp->sndq);
  96.     sp->sndcnt--;
  97.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  98.     restore(i_state);
  99. }
  100. /* Encode a packet in SLIP format */
  101. static
  102. struct mbuf *
  103. slip_encode(bp)
  104. struct mbuf *bp;
  105. {
  106.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  107.     register char *cp;
  108.     char c;
  109.  
  110.     /* Allocate output mbuf that's twice as long as the packet.
  111.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  112.      */
  113.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  114.     if(lbp == NULLBUF){
  115.         /* No space; drop */
  116.         free_p(bp);
  117.         return NULLBUF;
  118.     }
  119.     cp = lbp->data;
  120.  
  121.     /* Flush out any line garbage */
  122.     *cp++ = FR_END;
  123.  
  124.     /* Copy input to output, escaping special characters */
  125.     while(pullup(&bp,&c,1) == 1){
  126.         switch(uchar(c)){
  127.         case FR_ESC:
  128.             *cp++ = FR_ESC;
  129.             *cp++ = T_FR_ESC;
  130.             break;
  131.         case FR_END:
  132.             *cp++ = FR_ESC;
  133.             *cp++ = T_FR_END;
  134.             break;
  135.         default:
  136.             *cp++ = c;
  137.         }
  138.     }
  139.     *cp++ = FR_END;
  140.     lbp->cnt = cp - lbp->data;
  141.     return lbp;
  142. }
  143. /* Process incoming bytes in SLIP format
  144.  * When a buffer is complete, return it; otherwise NULLBUF
  145.  */
  146. static
  147. struct mbuf *
  148. slip_decode(dev,c)
  149. int16 dev;    /* Slip unit number */
  150. char c;        /* Incoming character */
  151. {
  152.     struct mbuf *bp;
  153.     register struct slip *sp;
  154.  
  155.     sp = &Slip[dev];
  156.     switch(uchar(c)){
  157.     case FR_END:
  158.         bp = sp->rbp;
  159.         sp->rbp = NULLBUF;
  160.         sp->rcnt = 0;
  161.         return bp;    /* Will be NULLBUF if empty frame */
  162.     case FR_ESC:
  163.         sp->escaped = 1;
  164.         return NULLBUF;
  165.     }
  166.     if(sp->escaped){
  167.         /* Translate 2-char escape sequence back to original char */
  168.         sp->escaped = 0;
  169.         switch(uchar(c)){
  170.         case T_FR_ESC:
  171.             c = FR_ESC;
  172.             break;
  173.         case T_FR_END:
  174.             c = FR_END;
  175.             break;
  176.         default:
  177.             sp->errors++;
  178.             break;
  179.         }
  180.     }
  181.     /* We reach here with a character for the buffer;
  182.      * make sure there's space for it
  183.      */
  184.     if(sp->rbp == NULLBUF){
  185.         /* Allocate first mbuf for new packet */
  186.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  187.             return NULLBUF; /* No memory, drop */
  188.         sp->rcp = sp->rbp->data;
  189.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  190.         /* Current mbuf is full; link in another */
  191.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  192.             /* No memory, drop whole thing */
  193.             free_p(sp->rbp);
  194.             sp->rbp = NULLBUF;
  195.             sp->rcnt = 0;
  196.             return NULLBUF;
  197.         }
  198.         sp->rbp1 = sp->rbp1->next;
  199.         sp->rcp = sp->rbp1->data;
  200.     }
  201.     /* Store the character, increment fragment and total
  202.      * byte counts
  203.      */
  204.     *sp->rcp++ = c;
  205.     sp->rbp1->cnt++;
  206.     sp->rcnt++;
  207.     return NULLBUF;
  208. }
  209. /* Process SLIP line input */
  210. void
  211. asy_rx(dev)
  212. int dev;
  213. {
  214.     char c;
  215.     struct mbuf *bp,*nbp;
  216.     struct phdr *phdr;
  217.     struct slip *sp;
  218.  
  219.     sp = &Slip[dev];
  220.  
  221.     for(;;){
  222.         c = get_asy(dev);
  223.         if((bp = slip_decode(dev,c)) == NULLBUF)
  224.             continue;    /* More to come */
  225.  
  226.         if((nbp = pushdown(bp,sizeof(struct phdr))) == NULLBUF){
  227.             free_p(bp);
  228.             continue;
  229.         }
  230.         phdr = (struct phdr *)nbp->data;
  231.         phdr->iface = sp->iface;
  232.         phdr->type = sp->type;
  233.         enqueue(&Hopper,nbp);
  234.     }
  235. }
  236. void
  237. asytxdone(dev)
  238. int16 dev;
  239. {
  240.     /* Kick the transmitter if it's idle */
  241.     if(stxrdy(dev))
  242.         asy_start(dev);
  243. }
  244.